/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */

package jnpf.engine.custom.config;

import jnpf.engine.custom.behavior.factory.CustomActivityBehaviorFactory;
import jnpf.engine.custom.idgen.ActivitiIDWorker;
import jnpf.engine.custom.life.CustomProcessEngineLifeStyleListener;
import jnpf.engine.custom.manager.CustomHistoryManager;
import jnpf.engine.custom.type.*;
import jnpf.engine.custom.variables.type.ArrayOrCollectionOrMapVariableType;
import jnpf.engine.custom.variables.type.JsonVariableType;
import jnpf.engine.custom.xml.impl.CustomCallActivityXMLConverter;
import jnpf.engine.custom.xml.impl.CustomManualTaskXMLConverter;
import jnpf.engine.custom.xml.impl.CustomReceiveTaskXMLConverter;
import jnpf.engine.custom.xml.impl.CustomSequenceFlowXMLConverter;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.common.engine.api.engine.EngineLifecycleListener;
import org.flowable.common.engine.impl.history.HistoryLevel;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.cfg.HttpClientConfig;
import org.flowable.engine.impl.cfg.DelegateExpressionFieldInjectionMode;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.spring.boot.EngineConfigurationConfigurer;
import org.flowable.variable.api.types.VariableType;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author
 * @date
 * @desc
 */
@Configuration
public class ActivitiConfig implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {
	@Resource
	private  DataSource dataSource;
	@Resource
	private  PlatformTransactionManager transactionManager;
	@Resource
	private ActivitiIDWorker activitiIDWorker;
	@Resource
	private FirstActivityAutoCompleteListener firstActivityAutoCompleteListener;
	@Resource
	private TaskCreatedInitListener taskCreatedInitListener;
	@Resource
	private TaskCompletedListener taskCompletedListener;
	@Resource
	private ProcessCompletedListener processCompletedListener;
	@Resource
	private ActivityStartedListener activityStartedListener;
	@Resource
	private ProcessCancelListener processCancelListener;
	@Resource
	private TaskDeletedListener taskDeletedListener;

	@Resource
	private VariableUpdatedListener variableUpdatedListener;

	@Resource
	private HistoryActivityInstanceEndedListener historyActivityInstanceEndedListener;
	@Resource
	private ArrayOrCollectionOrMapVariableType arrayOrCollectionOrMapVariableType;
	@Resource
	private JsonVariableType jsonVariableType;
	@Resource
	private CustomActivityBehaviorFactory customActivityBehaviorFactory;
	@Resource
	private CustomProcessEngineLifeStyleListener customProcessEngineLifeStyleListener;
	@Override
	public void configure(SpringProcessEngineConfiguration config)  {
//		CustomSpringProcessEngineConfiguration config = new CustomSpringProcessEngineConfiguration();
		config.setDisableEventRegistry(Boolean.TRUE);
		List<EngineLifecycleListener> list= new ArrayList<>();
		list.add(customProcessEngineLifeStyleListener);
		config.setEngineLifecycleListeners(list);
		config.setActivityFontName("宋体");
		config.setAnnotationFontName("宋体");
		config.setLabelFontName("黑体");
		config.setDataSource(dataSource);
		config.setTransactionManager(transactionManager);
		config.setDatabaseType(ProcessEngineConfigurationImpl.DATABASE_TYPE_MYSQL);
		config.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
		config.setIdGenerator(activitiIDWorker);
		config.setEnableSafeBpmnXml(true);
		config.setXmlEncoding("UTF-8");
		config.setEnableExecutionRelationshipCounts(true);
		config.setDbHistoryUsed(true);
		config.setHistory(HistoryLevel.AUDIT.getKey());
		config.setHistoryLevel(HistoryLevel.AUDIT);
		config.setBulkInsertEnabled(true);
		config.setMaxNrOfStatementsInBulkInsert(2000);
		config.setBatchSizeTasks(500);
		config.setBatchSizeProcessInstances(500);
		config.setCreateDiagramOnDeploy(true);
		config.setEnableDatabaseEventLogging(false);
		config.setEnableHistoricTaskLogging(false);
		config.setDisableIdmEngine(true);
		config.setFlowable5CompatibilityEnabled(false);
		config.setValidateFlowable5EntitiesEnabled(false);
		config.setAsyncExecutorActivate(false);
		config.setEnableEntityLinks(false);
		config.setEnableLogSqlExecutionTime(false);
		config.setEnableProcessDefinitionHistoryLevel(false);
		config.setExpressionCacheEnabled(true);
		config.setEnableProcessDefinitionInfoCache(true);
		config.setDelegateExpressionFieldInjectionMode(DelegateExpressionFieldInjectionMode.MIXED);
		Map<String, List<FlowableEventListener>> typeEventListeners=new HashMap<>();


		List<FlowableEventListener> taskCreatedEventListeners=new ArrayList<>();
		taskCreatedEventListeners.add(taskCreatedInitListener);
		taskCreatedEventListeners.add(firstActivityAutoCompleteListener);
		List<FlowableEventListener> taskCompletedListeners=new ArrayList<>();
		taskCompletedListeners.add(taskCompletedListener);
		List<FlowableEventListener> processCompletedListeners= new ArrayList<>();
		processCompletedListeners.add(processCompletedListener);
		List<FlowableEventListener> activityStartedListeners = new ArrayList<>();
		activityStartedListeners.add(activityStartedListener);
		List<FlowableEventListener> historyActivityStartedListeners=new ArrayList<>();
		historyActivityStartedListeners.add(historyActivityInstanceEndedListener);
		List<FlowableEventListener> cancelEventListeners=new ArrayList<>();
		cancelEventListeners.add(processCancelListener);

		//ENTITY DELETED
		//VARIABLE UPDATED

		List<FlowableEventListener> entityDeletedListeners= new ArrayList<>();
		entityDeletedListeners.add(taskDeletedListener);

		List<FlowableEventListener> variableUpdatedListeners = new ArrayList<>();
		variableUpdatedListeners.add(variableUpdatedListener);

		//添加自定义监听器
		typeEventListeners.put(FlowableEngineEventType.VARIABLE_UPDATED.name(), variableUpdatedListeners);
		typeEventListeners.put(FlowableEngineEventType.ENTITY_DELETED.name(),entityDeletedListeners);
		typeEventListeners.put(FlowableEngineEventType.PROCESS_CANCELLED.name(),cancelEventListeners);
		typeEventListeners.put(FlowableEngineEventType.HISTORIC_ACTIVITY_INSTANCE_ENDED.name(),historyActivityStartedListeners);
		typeEventListeners.put(FlowableEngineEventType.ACTIVITY_STARTED.name(),activityStartedListeners);
		typeEventListeners.put(FlowableEngineEventType.TASK_CREATED.name(),taskCreatedEventListeners);
		typeEventListeners.put(FlowableEngineEventType.TASK_COMPLETED.name(),taskCompletedListeners);
		typeEventListeners.put(FlowableEngineEventType.PROCESS_COMPLETED.name(),processCompletedListeners);
		config.setTypedEventListeners(typeEventListeners);
		List<VariableType> variableTypeList = new ArrayList<>();
		variableTypeList.add(arrayOrCollectionOrMapVariableType);
		variableTypeList.add(jsonVariableType);
		config.setCustomPreVariableTypes(variableTypeList);
		config.setActivityBehaviorFactory(customActivityBehaviorFactory);
		config.setHistoryManager(new CustomHistoryManager(config));
		//添加自定义xml转换器
		BpmnXMLConverter.addConverter(new CustomReceiveTaskXMLConverter());
		BpmnXMLConverter.addConverter(new CustomSequenceFlowXMLConverter());
		BpmnXMLConverter.addConverter(new CustomCallActivityXMLConverter());
		BpmnXMLConverter.addConverter(new CustomManualTaskXMLConverter());
		//http请求超时设置
		HttpClientConfig httpClientConfig=new HttpClientConfig();
		httpClientConfig.setConnectTimeout(10000);//连接超时
		httpClientConfig.setConnectionRequestTimeout(10000);//连接请求超时
		httpClientConfig.setSocketTimeout(10000);//双端建立socket连接
		httpClientConfig.setRequestRetryLimit(3);//请求失败之后重试次数
		config.setHttpClientConfig(httpClientConfig);
		config.setKnowledgeBaseCacheLimit(200);
		config.setProcessDefinitionCacheLimit(200);
	}

//	@Bean
//	@Primary
//	public TaskExecutor primaryTaskExecutor() {
//		return new ThreadPoolTaskExecutor();
//	}

}
